package com.uzai.console.web.alipay;

import com.alipay.api.CertAlipayRequest;
import com.alipay.api.internal.util.AlipaySignature;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import com.uzai.common.exception.BusinessException;
import com.uzai.common.result.ResponseCode;
import com.uzai.console.common.UzaiRespVo;
import com.uzai.console.common.utils.Tools;
import com.uzai.console.config.AliPayConfig;
import com.uzai.console.config.UzaiConsoleSysConfig;
import com.uzai.console.entity.AlipayDetail;
import com.uzai.console.entity.SysContract;
import com.uzai.console.enums.AlipaySubtypeEnum;
import com.uzai.console.enums.ContractStatusTypeEnum;
import com.uzai.console.jsonvo.contract.ContractSignAddressJson;
import com.uzai.console.mapper.AlipayDetailMapper;
import com.uzai.console.mapper.SysConfigMapper;
import com.uzai.console.mapper.SysContractMapper;
import com.uzai.console.service.alipaydetail.AlipayDetailService;
import com.uzai.console.service.contract.SysContractService;
import com.uzai.console.service.feign.UzaiContractFeignService;
import com.uzai.console.service.feign.dto.ContractOpeDto;
import com.uzai.console.web.BaseController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Map;

/**
 * @author jianghan
 * @date 2019-06-17 11:39
 */
@Api(value = "支付宝订单支付回调函数",tags = "淘宝|淘宝联盟", hidden = true)
@ApiSort(9)
@RestController
public class AlipayCallbackController extends BaseController {

    private static Logger logger = LoggerFactory.getLogger(AlipayCallbackController.class);

    @Autowired
    private SysConfigMapper sysConfigMapper;
    @Autowired
    private AlipayDetailService alipayDetailService;
    @Autowired
    private AlipayDetailMapper alipayDetailMapper;
    @Autowired
    private AliPayConfig aliPayConfig;
    @Autowired
    private UzaiConsoleSysConfig uzaiConsoleSysConfig;

    @Autowired
    private UzaiContractFeignService uzaiContractFeignService;

    @Autowired
    private SysContractMapper sysContractMapper;

    /**
     * 支付宝支付异步调用
     * @param request
     * @return
     * @throws Exception
     */
    @ApiOperation(value = "支付宝支付成功异步调用", hidden = true)
    @PostMapping("/alipay/notify")
    public Object pay_notify(HttpServletRequest request) {
        logger.info("支付完成进入异步通知");
        try {
            Map<String, String>  paramsMap = Tools.getParameterMap(request);
            String out_trade_no = paramsMap.get("out_trade_no");
            String trade_status = paramsMap.get("trade_status");
            logger.info("trade_no={},trade_status={}",out_trade_no,trade_status);
            String aliPayAppId = sysConfigMapper.selectByKey("aliPayAppId");
            String aliPayAppPriKey = sysConfigMapper.selectByKey("aliPayAppPriKey");
            //构造client(证书访问)
            CertAlipayRequest certAlipayRequest = aliPayConfig.getCertAlipayRequest(aliPayAppId, aliPayAppPriKey);

            boolean signVerified = AlipaySignature.rsaCertCheckV1(paramsMap, certAlipayRequest.getAlipayPublicCertPath(), aliPayConfig.getCHARSET(), aliPayConfig.getSIGN_TYPE());
            //无论同步异步都要验证签名
            if(signVerified){
                //处理自己系统的业务逻辑，如：将支付记录状态改为成功，需要返回一个字符串success告知支付宝服务器
                alipayDetailService.dealAlipayDetail(paramsMap);
                return "success";
            }else{
                //签名验证失败不处理业务逻辑
                return "failure";
            }
        } catch (Exception e) {
            logger.error("--error={}", e.getMessage());
            return "failure";
        }
    }

    /**
     * 支付宝支付成功同步调用
     * @param request
     * @return
     * @throws Exception
     */
    @ApiOperation(value = "支付宝支付成功同步调用", hidden = true)
    @RequestMapping("/alipay/return")
    public Object pay_return(HttpServletRequest request) throws IOException {

        logger.info("支付完成进入同步通知");

        Map<String, String> paramsMap = Tools.getParameterMap(request);

        String aliPayAppId = sysConfigMapper.selectByKey("aliPayAppId");
        String aliPayAppPriKey = sysConfigMapper.selectByKey("aliPayAppPriKey");
        //构造client(证书访问)
        //读取证书文件
        CertAlipayRequest certAlipayRequest = aliPayConfig.getCertAlipayRequest(aliPayAppId, aliPayAppPriKey);

        try {

            String out_trade_no = paramsMap.get("out_trade_no");
            AlipayDetail alipayDetail = alipayDetailMapper.selectByTradeno(out_trade_no);
            //跳转支付成功界面
            String return_url = uzaiConsoleSysConfig.getAlipayReturnUrl();
            if(alipayDetail != null){

                boolean signVerified = AlipaySignature.rsaCertCheckV1(paramsMap, certAlipayRequest.getAlipayPublicCertPath(), aliPayConfig.getCHARSET(), aliPayConfig.getSIGN_TYPE());

                if(signVerified){
                    if (AlipaySubtypeEnum.CONTRACT_SIGN_RECHARGE.getKey().equals(alipayDetail.getSubtype())) {
                        // 如果是合同签署协议单独走回调
                        extracted(alipayDetail);
                    } else {
                        getResponse().sendRedirect(return_url);
                    }

                }else{
                    //跳转支付失败界面
                    getResponse().sendRedirect(return_url + "?errorInfo="+ URLEncoder.encode("支付失败","UTF-8"));
                }
            }
        } catch (Exception e) {
            logger.error("--error={}", e.getMessage());
        }
        return "success";
    }

    private void extracted(AlipayDetail alipayDetail) throws IOException {
        SysContract sysContract = sysContractMapper.selectByType(alipayDetail.getMerId(), ContractStatusTypeEnum.UNDER_SIGNATURE.getKey());
        if (sysContract ==null ) {
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "当前合同不存在！");
        }
        if (sysContract.getSignUrl() != null) {
            getResponse().sendRedirect(sysContract.getSignUrl());
        } else {
            ContractOpeDto contractOpeDto = new ContractOpeDto();
            contractOpeDto.setSignFlowId(sysContract.getSignFlowId());
            UzaiRespVo<ContractSignAddressJson> contractInfo = uzaiContractFeignService.getContractSignUrl(contractOpeDto);
            if (contractInfo.getCode() == 200 && contractInfo.getData() != null) {
                getResponse().sendRedirect(contractInfo.getData().getUrl());
            }
        }
    }


}
